#ifndef TIEC_IDE_SERVICE_H
#define TIEC_IDE_SERVICE_H

#include "compiler.h"

namespace NS_TIEC {
  /// 文本内容改变描述信息
  struct TextChange {
    /// 文本改变的范围
    Range range {};
    /// 改变的长度
    size_t range_length {0};
    /// 改变后的内容
    String new_text;

    static TextChange fromJson(const char* json_string);
  };

  /// 带有光标信息的参数基类
  struct CursorParams {
    /// 文件Uri，如 file:///sdcard/Tiecode/Projects/Study1/Main.t
    Uri uri;
    /// 文件ID，用于快速比较判断
    Int64 source_id {-1};
    /// 光标所处位置
    Position position;
    /// 当前光标行文本
    String line_text;
  };

  /// 代码补全触发的参数信息
  struct CompletionParams : CursorParams {
    /// 触发代码提示的标识符
    String partial;
    /// 触发代码提示的字符
    String trigger_char;

    static CompletionParams fromJson(const char* json_string);
  };

  /// 要执行的文本内容修改结构体描述
  struct TextEdit {
    /// 文本修改的范围
    Range range;
    /// 修改后的内容
    String new_text;

    String toJson() const;
  };

  /// 要执行的项目修改操作
  typedef HashMap<Uri, List<TextEdit>, UriHash, UriEqual> ProjectEditMap;
  struct ProjectEdit {
    /// 项目中每个文件的文本修改操作
    ProjectEditMap file_edits;

    String toJson() const;
  };

  /// Hover操作的提示信息类型枚举
  enum struct MarkupKind {
    /// 纯文本
    kPlainText,
    /// Markdown
    kMarkdown
  };

  /// Hover操作的提示信息
  struct MarkupContent {
    MarkupKind kind {MarkupKind::kPlainText};
    /// 文本内容
    String text;
  };

  /// 代码补全项类型枚举
  enum struct CompletionItemKind {
    /// 关键字
    kKeyword = 0,
    /// 代码片段
    kSnippet,
    /// 类名
    kClass,
    /// 变量名
    kVariable,
    /// 普通方法
    kCommonMethod,
    /// 属性读方法
    kGetter,
    /// 属性写方法
    kSetter,
    /// 定义事件
    kEventDeclare,
    /// 注解
    kAnnotation,
    /// 常量补全
    kLiteral,
    /// 文件名
    kFile,
  };

  /// 代码补全项结构体
  struct CompletionItem {
    CompletionItemKind kind {CompletionItemKind::kKeyword};
    /// 名称
    String label;
    /// 详细描述信息
    String detail;
    /// 用于排序的key
    String sort_key;
    /// 符号名称，用于IDE统计符号使用频率，智能排序
    String symbol_name;
    /// 实际要插入到IDE编辑器中的内容
    String insert_text;
    /// 额外要执行的插入操作
    List<TextEdit> extra_edits;
  };

  /// 代码补全结果
  struct CompletionResult {
    List<CompletionItem> items;
    String toJson() const;
  };

  class IDEServiceImpl;
  /// IDE 服务封装（Completion、Lint、SematicHighlight、Hover、FindDefinition、FindImplementation、FindReferences等实现）
  class IDEService : public Compiler {
    friend class IDEServiceFactory;
  public:
    PTR<Context> getContext() override;
    void addTaskListener(const PTR<TaskListener>& listener) override;
    void removeTaskListener(const PTR<TaskListener>& listener) override;
    void setDiagnosticHandler(const PTR<DiagnosticHandler>& handler) override;

    /// 对所有源文件进行代码分析，首次打开项目时必须调用
    /// @param sources 项目的所有源文件
    void compile(const List<PTR<Source>>& sources) override;

    /// 通知环境中代码文件被修改（全量更新）
    /// @param source_uri 代码文件Uri
    /// @param new_text 修改后的内容
    void didChangeSource(const Uri& source_uri, String&& new_text) const;

    /// 通知环境中代码文件被修改（增量更新）
    /// @param source_uri 代码文件Uri
    /// @param change 增量修改的内容
    void didChangeSourceIncremental(const Uri& source_uri, const TextChange& change) const;

    /// 通知环境中有新文件创建
    /// @param source_uri 代码文件Uri
    /// @param initial_text 初始内容
    void didCreateSource(const Uri& source_uri, String&& initial_text) const;

    /// 通知环境中有文件被删除
    /// @param source_uri 代码文件Uri
    void didDeleteSource(const Uri& source_uri) const;

    /// 通知环境中文件被重命名
    /// @param old_uri 原来的Uri
    /// @param new_uri 新的Uri
    void didRenameSource(const Uri& old_uri, const Uri& new_uri) const;

    /// 获取光标处的代码补全
    /// @param params 代码补全参数
    /// @param result 代码补全结果
    /// @return 编译器分析的代码补全结果
    void requestCompletion(CompletionParams& params, CompletionResult& result) const;

    /// 取消上一次请求
    void cancel() const;
  private:
    explicit IDEService(UPTR<IDEServiceImpl>&& impl);
    UPTR<IDEServiceImpl> impl_;
  };

  /// IDE服务的创建工厂
  class IDEServiceFactory {
  public:
    /// 创建IDE服务对象
    /// \param context 编译器上下文
    /// \return IDE服务指针
    static PTR<IDEService> makeIDEService(const PTR<Context>& context);
  };
}

#endif //TIEC_IDE_SERVICE_H